home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / video / specialfx.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  28KB  |  1,000 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * specialfx.c: video effects demonstration program
  19.  *
  20.  *     - primarily for Galileo and IndyVideo
  21.  *
  22.  *      This program uses most of the VL example,
  23.  *    'simpleblend.c'
  24.  *        
  25.  *
  26.  * Notes:
  27.  *         modified 12/01/93 a.tang
  28.  *           modified 12/17/93 a.tang    'port' from nov15 to dec15 VL
  29.  *         modified  1/27/94 a.tang    'port' to 5.2 VL (images.Jan27)
  30.  *                    add PAL support
  31.  *    
  32.  * some of this code is generated by:
  33.  * Builder Xcessory 3.0 FT. (a UI builder)
  34.  *
  35.  */
  36.  
  37. #include "specialfx.h"
  38. #include <X11/keysym.h>
  39. float    Version_number = 2.0; /* version number */
  40.  
  41. XSizeHints    sizehints;    /* for window placement and size */
  42. Boolean        gfxonvid = True;/* for handling fg/bg */
  43. XtAppContext    theAppcontext;    /* for event processing */
  44. Display        *UIdisplay;    /* global UI event processing */
  45. void    myprocessXEvent();    /* process UI X events */
  46. void    VideoTracking(Window, int,int);        
  47. void    processXEvent(uint, void *);       
  48. void    processVLEvent(VLServer, VLEvent *, void *);  
  49. void    docleanup(void);
  50. void    usage(void);
  51. void    doErrorExit(char *s);
  52.  
  53. VLServer    vlSvr = NULL;
  54. VLPath        vlPath = -1;
  55. VLDevList    devlist;
  56. VLNode        src_vid;
  57. VLNode        src_scr;
  58. VLNode        drn_scr;
  59. VLNode        drn_vid;
  60. VLNode        blend_node;
  61. VLNode        mydev_node;
  62.  
  63. Display        *dpy;
  64. Window        srcwin;
  65. Window        drnwin;
  66. Window        vidinwin;
  67.  
  68. int        vout = VL_ANY;
  69. int        vin = VL_ANY;
  70. int        vinflag = 0;
  71. int        voutflag = 0;
  72. char        *_progname;
  73. char        *deviceName;
  74. int        devicenum = -1;
  75. int        debug = 0;
  76. int        ver = 0;
  77. int        input_timing;
  78. int        print_ids = 0;
  79. Boolean        zoomdown = False;
  80. int        fullx, fully;
  81.  
  82. Atom WM_DELETE_WINDOW;
  83. Atom WM_PROTOCOLS;
  84.  
  85. int lastw = 0, lasth = 0;
  86.  
  87. #define Debug    if (debug) printf
  88. #define fDebug    if (debug) fprintf
  89.  
  90. #define checkSetControlReturn(ret) \
  91.     if (ret != VLSuccess && vlErrno != VLValueOutOfRange) \
  92.         doErrorExit("vlSetControl");
  93.  
  94. #define SCR_XMAX 1280
  95. #define SCR_YMAX 1024
  96.  
  97. /* blend window bottom left, gfx-in window upper left: */
  98. #define DEFAULT_BLEND_X 10
  99. #define DEFAULT_BLEND_Y_NTSC 490 /* upper edge */
  100. #define DEFAULT_BLEND_Y_PAL 587 /* upper edge */
  101. #define DEFAULT_GFX_SRC_X 0
  102. #define DEFAULT_GFX_SRC_Y 0
  103.  
  104. /* blend window upper left, gfx-in window bottom left: */
  105. /*
  106. #define DEFAULT_BLEND_X 10
  107. #define DEFAULT_BLEND_Y 10 
  108. #define DEFAULT_GFX_SRC_X 10
  109. #define DEFAULT_GFX_SRC_Y 530
  110. */
  111. #define ESC_KEY '\006'
  112. #define USAGE \
  113. "%s: [-f] [-n <devicenum>] [-d] [-v <videonode>] [-o <videonode> ] [-z]\
  114. \n\
  115. \t-f\tdisable forking\n\
  116. \t-n\tdevice number to use\n\
  117. \t-d\tdebug mode\n\
  118. \t-v\tvideo input source to use (depends on hardware)\n\
  119. \t-o\tvideo output source to use (depends on hardware)\n\
  120. \t-z\tzoom down the video windows by one-half.\n\
  121. \t-h\tthis help message\n"
  122.  
  123. /* Constrain the window's aspect ratio */
  124. void
  125. constrainWindowResize(Display *dpy, Window win, int max_w, int max_h)
  126. {
  127.     XSizeHints xsh;
  128.  
  129.     xsh.min_aspect.x = xsh.max_aspect.x = 80;
  130.     xsh.min_aspect.y = xsh.max_aspect.y = 60;
  131.     xsh.min_width  = max_w;
  132.     xsh.min_height = max_h;
  133.     xsh.max_width  = max_w;
  134.     xsh.max_height = max_h;
  135.     xsh.flags = PAspect|PMinSize|PMaxSize;
  136.  
  137.     XSetWMNormalHints(dpy, win, &xsh);
  138.     XResizeWindow(dpy, win, max_w, max_h);
  139. }
  140. /* 
  141.  * Error reporting and program cleanup routine
  142.  */
  143. void
  144. doErrorExit(char *s)
  145. {
  146.     char foo[80];
  147.  
  148.     sprintf(foo,"%s(%s)", _progname, s);
  149.     vlPerror(foo);
  150.     docleanup();
  151. }
  152.  
  153. void
  154. initBlendControls()
  155. {
  156.     VLControlValue vlctlval;
  157.  
  158. vlctlval.intVal = 0;
  159. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_DETAIL,&vlctlval);
  160. vlctlval.intVal = 5;
  161. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_VALUE_CHROMA_U,&vlctlval);
  162. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_VALUE_CHROMA_V,&vlctlval);
  163. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_VALUE_LUMA,&vlctlval);
  164. vlctlval.intVal = 5;
  165. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_RANGE_CHROMA_U,&vlctlval);
  166. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_RANGE_CHROMA_V,&vlctlval);
  167. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_RANGE_LUMA,&vlctlval);
  168. vlctlval.intVal = 255;
  169. vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_FG_OPACITY,&vlctlval);
  170.     
  171. }
  172.  
  173. void 
  174. usage()
  175. {
  176.     fprintf(stderr, USAGE, _progname);
  177. }
  178.  
  179. /*
  180.  *    Main Program.
  181.  */
  182. main(argc, argv)
  183. int argc;
  184. char **argv;
  185. {
  186.     Arg args[256];
  187.     Cardinal argcnt;
  188.     Boolean argok;
  189.  
  190.     char *winname = NULL;
  191.     int opterr = 0;
  192.     int c, i;
  193.     int dev;
  194.     int ret;
  195.     int nofork = 0;
  196.     int x, y;
  197.     Atom WM_PROT_SET[2];
  198.     Atom _SGI_VIDEO;
  199.     VLControlValue val;
  200.     VLControlValue myval;
  201.     int zero = 0;
  202.  
  203.     int usehints = 1;    /* for size hints */
  204.     
  205.     _progname = argv[0];
  206.  
  207.     /*
  208.      * Parse command line options
  209.      * -f   disable forking
  210.      * -n   device number
  211.      * -d   set debugging
  212.      * -z   zoom down video windows 1/2
  213.      * -h   display help message
  214.      */
  215.     while ((c = getopt(argc, argv, "dv:o:n:Ifzh")) != EOF) 
  216.     {
  217.     switch(c) 
  218.     {
  219.         case 'f':
  220.         nofork = 1;
  221.         break;
  222.         case 'n':
  223.         devicenum = atoi(optarg);
  224.         printf("User specified device:%d\n", devicenum);
  225.         break;
  226.         case 'd':
  227.         debug++;
  228.         break;
  229.         case 'I':
  230.         print_ids = 1;
  231.         break;
  232.         case 'v':
  233.         vin = atoi(optarg);
  234.         vinflag = 1;
  235.         Debug ("video input = %d\n", vin);
  236.         break;
  237.         case 'o':
  238.         vout = atoi(optarg);
  239.         voutflag = 1;
  240.         Debug ("video output = %d\n", vout);
  241.         break;
  242.         case 'z':
  243.         zoomdown = True;
  244.         break;
  245.         case 'h':
  246.         usage();
  247.         exit(0);
  248.         break;
  249.     }
  250.     }
  251.  
  252.     if (opterr) 
  253.     {
  254.         usage();
  255.     exit(1);
  256.     }
  257.  
  258.  
  259.     XtToolkitInitialize();
  260.     theAppcontext = XtCreateApplicationContext();
  261.     UIdisplay = XtOpenDisplay(theAppcontext, 0, BX_APP_NAME, BX_APP_CLASS, 
  262.     0, 0, &zero, argv);
  263.  
  264. /*
  265. #ifndef XtSpecificationRelease
  266.         0, 0, (Cardinal*)&myargc, myargv);
  267. #else
  268. #if XtSpecificationRelease == 4
  269.         0, 0, (Cardinal*)&myargc, myargv);
  270. #else
  271.         0, 0, &myargc, myargv);
  272. #endif
  273. #endif
  274. */
  275.  
  276.     if(UIdisplay == NULL)
  277.     {
  278.     XtWarning("cannot open display");
  279.     exit(1);
  280.     }
  281.     /*
  282.      * So converters work.
  283.      */
  284.     XtInitializeWidgetClass(applicationShellWidgetClass);
  285.  
  286.     /*
  287.      * Register special BuilderXcessory converters.
  288.      */
  289.    RegisterBxConverters(theAppcontext); 
  290.  
  291.     /* Run in background if no-forking option not set */
  292.     if (!nofork) 
  293.     {
  294.     ret = fork();
  295.     switch (ret) 
  296.     {
  297.         case 0:
  298.         break;
  299.         
  300.         case -1:
  301.         fprintf(stderr, "%s: can't fork\n");
  302.         exit(1);
  303.         break;
  304.         
  305.         default:
  306.         exit(0);
  307.         break;
  308.     }
  309.     }
  310.  
  311.     /* Connect to the daemon */
  312.     if (!(vlSvr = vlOpenVideo(""))) 
  313.     {
  314.     printf("%s: opening video: %s\n",_progname,vlStrError(vlErrno));
  315.     exit(1);
  316.     }
  317.  
  318.     /* Get the list of devices the daemon supports */
  319.     if (vlGetDeviceList(vlSvr, &devlist) < 0) 
  320.     {
  321.     printf("%s: getting device list: %s\n",_progname,vlStrError(vlErrno));
  322.     exit(1);
  323.     }
  324.  
  325.     /* Make sure that the device the user requested (if any) is in the list */
  326.     if ((devicenum >= (int)devlist.numDevices) || (devicenum < -1))
  327.     {
  328.     if (devlist.numDevices == 1)
  329.         fprintf(stderr,"%s: The device number must be 0\n",_progname);
  330.     else
  331.         fprintf(stderr,"%s: The device number must be between 0 and %d\n",
  332.             _progname, devlist.numDevices-1);
  333.     exit(1);
  334.     }
  335.    /* find ev1 */
  336.     for (i=0; i<devlist.numDevices; i++) 
  337.         if (strcmp(devlist.devices[i].name,"ev1") == 0)
  338.         ev1num = i;
  339.     if ( (ev1num == -1) /* no ev1 found ... OR ...*/
  340.     || ((devicenum != -1) && (devicenum != ev1num))) /* non ev1 specified*/
  341.     {
  342.       printf("This program requires 'ev1' hardware.\a\n");
  343.       if (ev1num != -1) 
  344.     printf("Use device number '%d', or use the default mode\n",ev1num);
  345.       exit(1);
  346.     }else
  347.     {
  348.       printf("Setting device number to %d\n", ev1num);
  349.       devicenum = ev1num; /* allow default to work */
  350.     }
  351.  
  352.     /*
  353.      * Establish a path between the screen source and video
  354.      * drain. Then add a video source node and a screen drain
  355.      * node.
  356.      */
  357.  
  358.     /* Setup drain nodes on the screen and video */
  359.     drn_scr = vlGetNode(vlSvr, VL_DRN, VL_SCREEN, VL_ANY);
  360.  
  361.     if (voutflag == 0)
  362.     drn_vid = vlGetNode(vlSvr, VL_DRN, VL_VIDEO, VL_ANY);
  363.     else
  364.     drn_vid = vlGetNode(vlSvr, VL_DRN, VL_VIDEO, vout);
  365.     
  366.     /* Setup source nodes on the screen and video */
  367.     src_scr = vlGetNode(vlSvr, VL_SRC, VL_SCREEN, VL_ANY);
  368.  
  369.     if (vinflag == 0)
  370.     src_vid = vlGetNode(vlSvr, VL_SRC, VL_VIDEO, VL_ANY);
  371.     else
  372.     src_vid = vlGetNode(vlSvr, VL_SRC, VL_VIDEO, vin);
  373.  
  374.     mydev_node = vlGetNode(vlSvr, VL_DEVICE, 0,VL_ANY); 
  375.     if (mydev_node < 0)
  376.     {
  377.     printf("get device node error\n");
  378.     vlPerror(_progname);
  379.     exit(1);
  380.     }
  381.  
  382.     blend_node = vlGetNode(vlSvr, VL_INTERNAL, VL_BLENDER, VL_ANY);
  383.     if (blend_node < 0)
  384.     {
  385.     printf("get blend node error\n");
  386.     vlPerror(_progname);
  387.     exit(1);
  388.     }
  389.  
  390.     vlPath = -1;
  391.     /* If no device was specified... */
  392.     if (devicenum == -1)
  393.     {
  394.     /* Try to create the screen to video path */
  395.     vlPath = vlCreatePath(vlSvr, VL_ANY, src_scr, drn_vid);
  396.     /* Add the video source and screen drain nodes */
  397.     ret = vlAddNode(vlSvr, vlPath, src_vid);
  398.     if (!ret)
  399.     {
  400.         ret = vlAddNode(vlSvr, vlPath, drn_scr);
  401.     }
  402.     if (ret)
  403.     { /* Device doesn't support this path, these nodes */
  404.         vlDestroyPath(vlSvr, vlPath);
  405.         vlPath = -1;
  406.     } 
  407.     else 
  408.     { /* Path OK, get device info */
  409.         devicenum = vlGetDevice(vlSvr, vlPath);
  410.         deviceName = devlist.devices[devicenum].name;
  411.     }
  412.     }
  413.     else /* User specified a device */
  414.     {    /* Get the device info */
  415.     deviceName = devlist.devices[devicenum].name;
  416.         /* Try to create the screen to video path */
  417.     vlPath = vlCreatePath(vlSvr, devicenum, src_scr, drn_vid);
  418.     /* Add the video source and screen drain nodes */
  419.     ret = vlAddNode(vlSvr, vlPath, src_vid);
  420.     if (!ret)
  421.     {
  422.         ret = vlAddNode(vlSvr, vlPath, drn_scr);
  423.     }
  424.     if (ret)
  425.     {  /* Device doesn't support this path, these nodes */
  426.         vlDestroyPath(vlSvr, vlPath);
  427.         vlPath = -1;
  428.     }
  429.     }
  430.  
  431.     if (vlAddNode(vlSvr, vlPath, mydev_node))
  432.     {
  433.     vlPerror("Add Device Node");
  434.     vlDestroyPath(vlSvr, vlPath);
  435.     vlPath = -1;
  436.     }
  437.  
  438.     if (vlAddNode(vlSvr, vlPath, blend_node))
  439.     {
  440.     vlPerror("Add Blend Node");
  441.     vlDestroyPath(vlSvr, vlPath);
  442.     vlPath = -1;
  443.     }
  444.  
  445.     if (vlPath == -1)
  446.     { /* Couldn't create the path, quit */
  447.     vlPerror("Path Setup");
  448.     docleanup();
  449.     }
  450.  
  451.     /* Set up the hardware for and define the usage of the path */
  452.    if (vlSetupPaths(vlSvr,(VLPathList)&vlPath,1,VL_SHARE,VL_READ_ONLY)<0)
  453.     {
  454.     printf("setup paths error\n");
  455.     vlPerror(_progname);
  456.     exit(1);
  457.     }
  458.     /* initialize to ev1 slave mode. */
  459.  
  460.     vlGetControl(vlSvr, vlPath, mydev_node, VL_SYNC, &val);
  461.  
  462. #ifdef DEBUG
  463.     printf("\n");
  464.     printf("initial sync value  = %d\n", val.intVal);
  465.     printf("ev1 value = %d\n", VL_EV1_SYNC_SLAVE);
  466. #endif
  467.     /* set to slave mode */
  468.  
  469.     val.intVal = VL_EV1_SYNC_SLAVE;
  470.     if (vlSetControl(vlSvr, vlPath, mydev_node, VL_SYNC, &val) < 0)
  471.     {
  472.       printf("set sync mode error\n");
  473.       vlPerror(_progname);
  474.       exit(1);
  475.     }
  476.     vlGetControl(vlSvr, vlPath, mydev_node, VL_SYNC, &val);
  477.  
  478. #ifdef DEBUG
  479.     printf ("after set value, sync val = %d\n", val.intVal);
  480. #endif
  481.     /* get the current input timing */
  482.     vlGetControl(vlSvr, vlPath, src_vid, VL_TIMING, &val);
  483.     input_timing = val.intVal;
  484.  
  485.     /* Get the current size of the drain window */
  486.     vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val);
  487.     fullx = lastw = val.xyVal.x;
  488.     fully = lasth = val.xyVal.y;
  489.     Debug("fullx,fully = %d,%d\n", fullx,fully);
  490.  
  491.     /* for drnwin (blend output): zoom 1/2 if non 525 */
  492.     if ((input_timing == VL_TIMING_625_SQ_PIX) ||
  493.     (input_timing == VL_TIMING_625_CCIR601) ||
  494.     (input_timing == VL_TIMING_625_4FSC))
  495.     {
  496.     Debug("non 525 timing detected\n");
  497.     if (lasth != 576) lasth = 576;
  498.     zoomdown = True;
  499.     }
  500.     if (zoomdown)
  501.     {
  502.     val.fractVal.numerator = 1;
  503.     val.fractVal.denominator = 2;
  504.     if (vlSetControl(vlSvr, vlPath, drn_scr, VL_ZOOM, &val)<0)
  505.        vlPerror("WARNING: set zoom error\n");
  506.     val.xyVal.x = fullx; /* set val.xyVal.x to full size */
  507.     val.xyVal.y = fully; /* set val.xyVal.y to full size */
  508.     if (vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val)<0)
  509.        vlPerror("WARNING: set size error\n");
  510.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  511.     /* now set lastw and lasth to the drain size again */
  512.     lastw = lastw/2; /* to go with zoom 1/2 */
  513.     lasth = lasth/2; /* to go with zoom 1/2 */
  514.     }    
  515.      /* Set the source to the full size */
  516.     val.xyVal.x = fullx;
  517.     val.xyVal.y = fully;
  518.     Debug("setting source VLSIZE to = %d,%d\n", val.xyVal.x,val.xyVal.y);
  519.     if ( vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val)!= 0)
  520.     {
  521.       printf("set vlsize error\n");
  522.       vlPerror(_progname);
  523.       exit(1);
  524.     }
  525.     /* Make sure there's enough room for a source window of the same size */ 
  526.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  527. #ifdef oldcode
  528.     if (((val.xyVal.x+lastw)>SCR_XMAX) || ((val.xyVal.y+lasth)>SCR_YMAX)) 
  529. #endif
  530.     if ((val.xyVal.y+lasth)>SCR_YMAX) 
  531.     {
  532.     printf("%s: unable to make two full size windows\n", _progname);
  533.     docleanup();
  534.     }
  535.     /* Set the keyer mode, keyer source and blend controls */
  536.     val.intVal = VL_EV1_KEYERMODE_LUMA;
  537.     if (vlSetControl(vlSvr, vlPath, blend_node, VL_EV1_KEYER_MODE, &val)<0)
  538.     {
  539.       printf("set keyer mode error\n");
  540.       vlPerror(_progname);
  541.       exit(1);
  542.     }
  543.     val.intVal = src_scr;
  544. /*
  545.     if (vlSetControl(vlSvr, vlPath, blend_node, VL_EV1_KEYER_SOURCE, &val)<0)
  546.     {
  547.       printf("set keyer source error\n");
  548.       vlPerror(_progname);
  549.       exit(1);
  550.     }
  551. */
  552.     val.intVal = src_scr;
  553.     if (vlSetControl(vlSvr, vlPath, blend_node, VL_BLEND_A, &val)!=0)
  554.     {
  555.       printf("set blend A error\n");
  556.       vlPerror(_progname);
  557.       exit(1);
  558.     }
  559.     val.intVal = src_vid;
  560.     if (vlSetControl(vlSvr, vlPath, blend_node, VL_BLEND_B, &val)!=0)
  561.     {
  562.       printf("set blend B error\n");
  563.       vlPerror(_progname);
  564.       exit(1);
  565.     }
  566.  
  567.     /* open a display */
  568.     if (!(dpy = XOpenDisplay(""))) 
  569.     {
  570.     printf("%s: can't open display\n", _progname);
  571.     exit(1);
  572.     }
  573.     /* create the source window to be the full size */
  574.  
  575.     srcwin = XCreateWindow(dpy, RootWindow(dpy, 0),
  576.                 DEFAULT_GFX_SRC_X, DEFAULT_GFX_SRC_Y,
  577.                 fullx, fully, 0,
  578.                 CopyFromParent, CopyFromParent, CopyFromParent,
  579.                 (ulong) 0, NULL);
  580.  
  581.     drnwin = XCreateWindow(dpy, RootWindow(dpy, 0), 
  582.                 DEFAULT_BLEND_X, DEFAULT_BLEND_Y_PAL, 
  583.                 lastw, lasth, 0,
  584.                 CopyFromParent, CopyFromParent, CopyFromParent,
  585.                 (ulong) 0, NULL);
  586.  
  587.     _SGI_VIDEO = XInternAtom(dpy, "_SGI_VIDEO", False);
  588.     WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  589.     WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
  590.     WM_PROT_SET[0] = WM_DELETE_WINDOW;
  591.     WM_PROT_SET[1] = _SGI_VIDEO;
  592.     XSetWMProtocols(dpy,drnwin, WM_PROT_SET, 2);
  593.     XSetWMProtocols(dpy,srcwin, WM_PROT_SET, 2);  
  594.     XStoreName(dpy, srcwin, "Video Blending Source"); 
  595.     XStoreName(dpy, drnwin, "Video Blending");
  596.     
  597.     /* Adjust source window's aspect ratio *//* not needed - not managed */
  598.     /*    constrainWindowResize(dpy, srcwin, lastw, lasth); */
  599.     /* Turn off the source window's border *//* not needed - not managed */
  600.     /*     noborders(dpy, srcwin); */
  601.  
  602.     /* Adjust the drain window's aspect ratio */
  603.     constrainWindowResize(dpy, drnwin, lastw, lasth);
  604.  
  605.     /* Set the video to appear in window drnwin */
  606.     val.intVal = drnwin;
  607.     if (vlSetControl(vlSvr, vlPath, drn_scr, VL_WINDOW, &val)<0)
  608.        vlPerror("WARNING: set VL_WINDOW error\n");
  609.  
  610.     /* Make sure there's room for both the source and drain window */
  611.     vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val);
  612.  
  613. #ifdef oldcode
  614.     if (((val.xyVal.x+lastw)>SCR_XMAX) || ((val.xyVal.y+lasth)>SCR_YMAX)) 
  615. #endif
  616.     if ((val.xyVal.y+lasth)>SCR_YMAX) 
  617.     {
  618.     printf("%s: unable to make two full size windows\n", _progname);
  619.     docleanup();
  620.     }
  621.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  622. #ifdef oldcode
  623.     if (((val.xyVal.x+lastw)>SCR_XMAX) || ((val.xyVal.y+lasth)>SCR_YMAX)) 
  624. #endif
  625.     if ((val.xyVal.y+lasth)>SCR_YMAX) 
  626.     {
  627.     printf("%s: unable to make two full size windows\n", _progname);
  628.     docleanup();
  629.     }
  630.     /* Get the location of the screen source */
  631.     vlGetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
  632.     /* Set the controls for the location of the src_scr node: */
  633.     /* note: doing it before this point, we seem to lose the setting */
  634.     myval.xyVal.x = DEFAULT_GFX_SRC_X;
  635.     myval.xyVal.y = DEFAULT_GFX_SRC_Y;
  636.     if(vlSetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &myval)<0)
  637.        vlPerror("WARNING: set VL_ORIGIN error\n");
  638.     vlGetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
  639.  
  640.     /* Print the node and path IDs for cmd line users */
  641.     if (print_ids)
  642.     {
  643.     printf("SPECIALFX NODE IDs:\n");
  644.     printf("screen source = %d\n", src_scr);
  645.     printf("video source = %d\n", src_vid);
  646.     printf("screen drain = %d\n", drn_scr);
  647.     printf("video drain = %d\n", drn_vid);
  648.     printf("device = %d\n", mydev_node);
  649.     printf("blend = %d\n", blend_node);
  650.     printf("PATH ID = %d\n", vlPath);
  651.     }
  652.  
  653.     /* set up size and placement hint info */
  654.     sizehints.x = DEFAULT_BLEND_X; 
  655.     if ((input_timing == VL_TIMING_625_SQ_PIX) || 
  656.     (input_timing == VL_TIMING_625_CCIR601) ||
  657.     (input_timing == VL_TIMING_625_4FSC))
  658.     {
  659.     sizehints.y = DEFAULT_BLEND_Y_PAL;
  660.     }else
  661.     {
  662.     sizehints.y = DEFAULT_BLEND_Y_NTSC;
  663.     }
  664.  
  665.     if (usehints) {
  666.     bzero(&sizehints, sizeof(XSizeHints));
  667.         sizehints.base_width = 640; 
  668.         sizehints.base_height = 486; 
  669.         sizehints.min_width = sizehints.max_width = sizehints.base_width;
  670.         sizehints.min_height = sizehints.max_height = sizehints.base_height;
  671.         sizehints.flags = USPosition; 
  672.      XSetWMNormalHints(dpy, drnwin, &sizehints);
  673.     }
  674.     val.xyVal.x = sizehints.x;
  675.     val.xyVal.y = sizehints.y;
  676.     Debug("setting screen drain origin to: %d %d\n", val.xyVal.x, val.xyVal.y);
  677.     if (vlSetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val)<0)
  678.        vlPerror("WARNING: set drn origin error\n");
  679.     if (vlGetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val)<0)
  680.        vlPerror("WARNING: get drn origin error\n");
  681.     Debug("got screen drain origin: %d %d\n", val.xyVal.x, val.xyVal.y);
  682.     if (vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val)<0)
  683.        vlPerror("WARNING: get drn origin error\n");
  684.     Debug("got screen drain size: %d %d\n", val.xyVal.x, val.xyVal.y);
  685.     XMapWindow(dpy, drnwin);
  686.  
  687.     /* Set up the hardware for and define the usage of the path */
  688.     if (vlSetupPaths(vlSvr, (VLPathList)&vlPath, 1, VL_SHARE, VL_SHARE) < 0)
  689.     {
  690.     printf("setup paths error\n");
  691.     vlPerror(_progname);
  692.     exit(1);
  693.     }
  694.  
  695.     /* reset zoomdown now, after the SHARE SHARE vlSetupPaths */
  696.     if (zoomdown)
  697.     {
  698.     Debug("Zooming down...\n");
  699.     val.fractVal.numerator = 1;
  700.     val.fractVal.denominator = 2;
  701.     if (vlSetControl(vlSvr, vlPath, drn_scr, VL_ZOOM, &val)<0)
  702.        vlPerror("WARNING: set zoom error\n");
  703.     val.xyVal.x = fullx/2;
  704.     val.xyVal.y = fully/2;
  705.     if (vlSetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val)<0)
  706.         vlPerror("WARNING: set size error\n");
  707.     XResizeWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
  708.     XSync(dpy, 0);
  709.     XSync(dpy, 0);
  710.     val.xyVal.x = fullx; /* set val.xyVal.x to full size */
  711.     val.xyVal.y = fully; /* set val.xyVal.y to full size */
  712.     if (vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val)<0)
  713.        vlPerror("WARNING: set size error\n");
  714.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  715.     }    
  716.     /* Set screen source origin and size now after vlSetupPaths */
  717.     Debug("screen source origin: %d %d\n", val.xyVal.x, val.xyVal.y);
  718.     myval.xyVal.x = fullx;
  719.     myval.xyVal.y = fully;
  720.     if (vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &myval)<0)
  721.        vlPerror("WARNING: set size error\n");
  722.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  723.     Debug("Gotton screen source size: %d %d\n", val.xyVal.x, val.xyVal.y);
  724.     XSelectInput(dpy, drnwin, KeyPressMask|VisibilityChangeMask
  725.                 |ExposureMask|StructureNotifyMask);
  726.     XSync(dpy, 0);
  727.  
  728.     initBlendControls(); 
  729.  
  730. /* ------ start build UI widgets ------ */
  731. /*
  732.  * The applicationShell is created as an unrealized
  733.  * parent for multiple topLevelShells.  The topLevelShells
  734.  * are created as popup children of the applicationShell.
  735.  * This is a recommendation of Paul Asente & Ralph Swick in
  736.  * _X_Window_System_Toolkit_ p. 677.
  737.  */
  738.     argcnt = 0;
  739.     AppShell = XtAppCreateShell( BX_APP_NAME, BX_APP_CLASS,
  740.             applicationShellWidgetClass, UIdisplay, args, argcnt);
  741.  
  742.     XtInitializeWidgetClass(topLevelShellWidgetClass);
  743.     argcnt = 0;
  744.     XtSetArg(args[argcnt], XmNkeyboardFocusPolicy, XmPOINTER); argcnt++;
  745.     XtSetArg(args[argcnt], XmNx, 450); argcnt++;
  746.     XtSetArg(args[argcnt], XmNy, 487); argcnt++;
  747.     Shell000 = XtCreatePopupShell( "topLevelShell", 
  748.         topLevelShellWidgetClass, AppShell, args, argcnt);
  749.  
  750.     MainWindow = CreatemainWindow(Shell000);
  751.  
  752.     Shell001 = CreatechromaShell(AppShell);
  753.     ChromaBBoard = CreatechromaBBoard(Shell001);
  754.  
  755.     Shell002 = CreatelumaShell(AppShell);
  756.     LumaBBoard = CreatelumaBBoard(Shell002);
  757.  
  758.     Shell003 = CreateswitchShell(AppShell);
  759.     SwitchBBoard = CreateswitchBBoard(Shell003);
  760.  
  761.     XtManageChild(MainWindow);
  762.     XtPopup(XtParent(MainWindow), XtGrabNone);
  763.  
  764. /* ------ end build UI widgets ----- */
  765.     /* Specify a file descriptor and pending check function for VL events */
  766.     vlRegisterHandler(vlSvr, ConnectionNumber(dpy), processXEvent,
  767.               (VLPendingFunc)XPending, dpy);
  768.               
  769.     /* Now, my UI X events */
  770.     vlRegisterHandler(vlSvr, ConnectionNumber(UIdisplay), myprocessXEvent,
  771.               (VLPendingFunc)XPending, UIdisplay);
  772.               
  773.     /* Set up event handler routine as callback for all events */
  774.     vlAddCallback(vlSvr, vlPath, VLAllEventsMask, processVLEvent, NULL);
  775.  
  776.     /* Start the data transfer immediately (i.e. don't wait for trigger) */
  777.     vlBeginTransfer(vlSvr, vlPath, 0, NULL);
  778.  
  779.     vlMainLoop();
  780.  
  781. } /* end main */
  782.  
  783. /*
  784.  * VideoTracking - if the user changes the size of the window, 
  785.  * update the video to reflect the new size and position.
  786.  */
  787. void
  788. VideoTracking(Window win, int x, int y)
  789. {
  790.     Window dummyWin;
  791.     VLControlValue val;
  792.  
  793.     /* Get X's idea of origin */
  794.     XTranslateCoordinates(dpy, win, RootWindow(dpy, DefaultScreen(dpy)),
  795.                           0, 0,
  796.                           &x, &y,
  797.                           &dummyWin);
  798.  
  799.     /* Try to make vl match X */
  800.     val.xyVal.x = x;
  801.     val.xyVal.y = y;
  802.     if (win == drnwin)
  803.     vlSetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
  804.     else
  805.     vlSetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
  806. }
  807.  
  808. /* 
  809.  * VLEvent processing for video to screen.
  810.  * We only deal with control changed events.
  811.  */
  812. void
  813. processVLEvent(VLServer vlSvr, VLEvent *ev, void *dummy)
  814. {
  815.     VLControlChangedEvent *cev = (VLControlChangedEvent *) ev;
  816.     VLControlValue val;
  817.  
  818.     Debug("VL event.type = %d\n", ev->reason);
  819.     switch (ev->reason)
  820.     {   /* Ignore all but a change in the drain's location */
  821.     case VLControlChanged:
  822.         if (cev->type == VL_ORIGIN)
  823.         {
  824.         if (cev->node == drn_scr)
  825.         {   /* Drain moved, move window accordingly */
  826.             vlGetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
  827.             XMoveWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
  828.         }
  829.         else if (cev->node == src_scr)
  830.         {   /* Source moved, move window accordingly */
  831.  
  832.             vlGetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
  833.             XMoveWindow(dpy, srcwin, val.xyVal.x, val.xyVal.y);
  834.  
  835.         }
  836.         }
  837.     break;
  838.     }
  839. }
  840.  
  841. /* my XEvent processing for UI */
  842. void
  843. myprocessXEvent()
  844. {
  845.     XEvent event;
  846.  
  847.     /* do the XtAppMainLoop next and dispatch here */
  848.     XtAppNextEvent(theAppcontext, &event);
  849.     /* got an XtAppNextEvent */
  850.     XtDispatchEvent(&event);
  851. }
  852.  
  853. /* XEvent processing for video to screen */
  854. void
  855. processXEvent(uint fd, void *source)
  856. {
  857.     int ret,i;
  858.     XEvent event;
  859.     VLControlValue val;
  860.     VLControlValue myval;
  861.  
  862.     if (source == (caddr_t)dpy) 
  863.     {
  864.     XEvent ev;
  865.     
  866.     XNextEvent(dpy, &ev);
  867.     switch (ev.type) 
  868.     {
  869.         case ClientMessage:
  870.         if (ev.xclient.message_type == WM_PROTOCOLS)
  871.             if (ev.xclient.data.l[0] == WM_DELETE_WINDOW)
  872.             docleanup();
  873.         break;
  874.         
  875.         case Expose:        /* These really don't effect us */
  876.         case GraphicsExpose:
  877.         case VisibilityNotify:
  878.         break;
  879.         
  880.         case ConfigureNotify:       /* Window moved or changed size */
  881.         VideoTracking(ev.xany.window, ev.xconfigure.x,ev.xconfigure.y);
  882.         break;
  883.         
  884.         case KeyPress: 
  885.         {
  886.         XKeyEvent *kev = (XKeyEvent *)&ev;
  887.         KeySym keysym;
  888.         char buf[4];
  889.                 
  890.         XLookupString(kev, buf, 1, &keysym, 0);
  891.         switch (keysym)
  892.         {
  893.             /* Pan right */
  894.             case XK_Left:
  895.             /* Get current offset */
  896.             if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
  897.                 doErrorExit("get offset");
  898.             val.xyVal.x++;
  899.             ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
  900.             /* Make sure offset is OK */
  901.             checkSetControlReturn(ret);
  902.             break;
  903.             
  904.             /* Pan left */
  905.             case XK_Right:
  906.             /* Get current offset */
  907.             if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
  908.                 doErrorExit("get offset");
  909.             val.xyVal.x--;
  910.             ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
  911.             /* Make sure offset is OK */
  912.             checkSetControlReturn(ret);
  913.             break;
  914.             
  915.             /* Pan up */
  916.             case XK_Down:
  917.             /* Get current offset */
  918.             if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
  919.                 doErrorExit("get offset");
  920.             val.xyVal.y--;
  921.             ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
  922.             /* Make sure offset is OK */
  923.             checkSetControlReturn(ret);
  924.             break;
  925.             
  926.             /* Pan down */
  927.             case XK_Up:
  928.             /* Get current offset */
  929.             if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
  930.                 doErrorExit("get offset");
  931.             val.xyVal.y++;
  932.             ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
  933.             /* Make sure offset is OK */
  934.             checkSetControlReturn(ret);
  935.             break;
  936.         }
  937.         switch (buf[0]) 
  938.         {   
  939.             case '+':
  940.             val.fractVal.numerator = 1;
  941.             val.fractVal.denominator = 1;
  942.             if (vlSetControl(vlSvr, vlPath, \
  943.                 drn_scr, VL_ZOOM, &val)<0)
  944.                 vlPerror("WARNING: set zoom error\n");
  945.             val.xyVal.x = fullx;
  946.             val.xyVal.y = fully;
  947.             if (vlSetControl(vlSvr, vlPath, \
  948.                 drn_scr, VL_SIZE, &val)<0)
  949.                 vlPerror("WARNING: set size error\n");
  950.             XResizeWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
  951.             XSync(dpy, 0);
  952.             XSync(dpy, 0);
  953.  
  954.             break;
  955.             case '-':
  956.             val.fractVal.numerator = 1;
  957.             val.fractVal.denominator = 2;
  958.             if (vlSetControl(vlSvr, vlPath, \
  959.                 drn_scr, VL_ZOOM, &val)<0)
  960.                 vlPerror("WARNING: set zoom error\n");
  961.             val.xyVal.x = fullx/2;
  962.             val.xyVal.y = fully/2;
  963.             if (vlSetControl(vlSvr, vlPath, \
  964.                 drn_scr, VL_SIZE, &val)<0)
  965.                 vlPerror("WARNING: set size error\n");
  966.             XResizeWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
  967.             XSync(dpy, 0);
  968.             XSync(dpy, 0);
  969.  
  970.             break;
  971.             /* Quit */
  972.             case 'q':
  973.             case 'Q':
  974.             case ESC_KEY:
  975.             docleanup();
  976.             break;
  977.             
  978.             default:
  979.             break;
  980.         }
  981.         }
  982.     }
  983.     } /* end if source == dpy */
  984. }
  985.  
  986. /* Dispose of the vl structures */
  987. void
  988. docleanup(void)
  989. {   /* End the data transfer */
  990.     vlEndTransfer(vlSvr, vlPath);
  991.      
  992.     /* Destroy the path, free it's memory */
  993.     vlDestroyPath(vlSvr, vlPath);
  994.  
  995.     /* Disonnect from the daemon */
  996.     vlCloseVideo(vlSvr);
  997.  
  998.     exit(0);
  999. }
  1000.